//package com.hsb.seckill.config;
//
//import com.fasterxml.jackson.databind.ObjectMapper;
//import com.google.common.util.concurrent.RateLimiter;
//import com.hsb.seckill.entity.User;
//import com.hsb.seckill.exception.GlobalException;
//import com.hsb.seckill.result.ResBean;
//import com.hsb.seckill.result.ResBeanEnum;
//import com.hsb.seckill.service.UserService;
//import com.hsb.seckill.utils.CookieUtil;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.data.redis.core.RedisTemplate;
//import org.springframework.stereotype.Component;
//import org.springframework.util.StringUtils;
//import org.springframework.web.method.HandlerMethod;
//import org.springframework.web.servlet.HandlerInterceptor;
//
//import javax.servlet.http.HttpServletRequest;
//import javax.servlet.http.HttpServletResponse;
//import java.io.IOException;
//import java.io.PrintWriter;
//import java.util.concurrent.TimeUnit;
//
///**
// * 限流拦截器
// */
//@Component
//public class AccessLimitInterceptor implements HandlerInterceptor {
//
//    @Autowired
//    private UserService userService;
//    @Autowired
//    private RedisTemplate redisTemplate;
//
//    // 进入方法前处理，返回true放行
//    @Override
//    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//        // 判断handler是否是要处理的方法
//        if (handler instanceof HandlerMethod) {
//            // 获取当前用户
//            User user = getUser(request, response);
//            //将user存到当前的线程中
//            UserContent.setUser(user);
//            // 处理的方法
//            HandlerMethod method = (HandlerMethod) handler;
//            // 获取方法上的AccessLimit注解
//            AccessLimit accessLimit = method.getMethodAnnotation(AccessLimit.class);
//            if (accessLimit == null) {
//                return true;
//            }
//            //获取注解的属性值
//            int second = accessLimit.second();
//            int maxCount = accessLimit.maxCount();
//            boolean needLogin = accessLimit.needLogin();
//            //获取uri
//            String uri = request.getRequestURI();
//            if (needLogin) {
//                if (user == null){
//                    render(response,ResBeanEnum.USER_NOT_LOGIN);
//                    return false;
//                }
//            }
//            ////令牌桶算法
//            ////每秒产生5个令牌，相当于5QPS,每秒最多处理5个请求
//            //RateLimiter rateLimiter = RateLimiter.create(maxCount);
//            ////尝试获取令牌，获取成功返回true,失败返回false
//            //boolean b = rateLimiter.tryAcquire();
//            //if (!b){//获取令牌失败，则返回错误提示信息
//            //    render(response,ResBeanEnum.ACCESS_LIMIT_REAHCED);
//            //    return false;
//            //}
//
//            //固定时间窗口算法  限制访问次数，5秒内访问5次
//            Integer count = (Integer) redisTemplate.opsForValue().get(uri+":"+user.getId());
//            if (count == null){
//                redisTemplate.opsForValue().set(uri+":"+user.getId(),1,second, TimeUnit.SECONDS);
//            }else if (count<maxCount){
//                redisTemplate.opsForValue().increment(uri+":"+user.getId());
//            }else {
//                render(response,ResBeanEnum.ACCESS_LIMIT_REAHCED);
//                return false;
//            }
//        }
//        return true;
//    }
//
//    /**
//     * 构建返回对象
//     * @param response
//     * @param resBeanEnum
//     */
//    private void render(HttpServletResponse response,ResBeanEnum resBeanEnum) throws IOException {
//        response.setContentType("application/json");
//        response.setCharacterEncoding("UTF-8");
//        PrintWriter out = response.getWriter();
//        ResBean resBean = ResBean.error(resBeanEnum);
//        out.write(new ObjectMapper().writeValueAsString(resBean));
//        out.flush();
//        out.close();
//    }
//
//    /**
//     * 获取当前登录用户
//     * @param request
//     * @param response
//     * @return
//     */
//    private User getUser (HttpServletRequest request, HttpServletResponse response){
//        String ticket = CookieUtil.getCookieValue(request, "userTicket");
//        if (StringUtils.isEmpty(ticket)) {
//            return null;
//        }
//        return userService.getUserByCookie(ticket, request, response);
//    }
//}
